package com.hare.system_server.serice.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hare.auth.utils.SecurityUtils;
import com.hare.common.exception.ServiceException;
import com.hare.common.global.constant.BaseConstant;
import com.hare.system_api.dto.SysMenuDTO;
import com.hare.system_api.po.SysCategoryMenu;
import com.hare.system_api.vo.MenuTreeVO;
import com.hare.system_api.vo.MetaVO;
import com.hare.system_api.vo.RoutesVO;
import com.hare.system_api.vo.SysMenuVO;
import com.hare.system_server.mapper.SysMenuMapper;
import com.hare.system_server.serice.SysMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: Hare
 * @description: 菜单实现Service
 * @author: Hare
 * @create: 2022-11-04 09:22
 * @Version 6.0.1
 **/
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysCategoryMenu> implements SysMenuService {


    @Autowired
    SysMenuMapper sysMenuMapper;


    /**
     * 根据用户id查询菜单
     *
     * @param userId 用户ID
     * @return
     */
    @Override
    public List<SysMenuVO> selectMenuTreeByUserId(String userId) {
        List<SysMenuVO> sysMenuVOList = new ArrayList<>();
        try {
            // 是否是超级管理员判断
            if (SecurityUtils.isAdmin(userId)) {
                sysMenuVOList = sysMenuMapper.selectMenuTreeAll();
            } else {
                sysMenuVOList = sysMenuMapper.selectMenuTreeByUserId(userId);
            }
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
        return getMenuList(sysMenuVOList);
    }


    /**
     * 组装路由信息
     *
     * @param menu 菜单信息
     * @return
     */
    @Override
    public List<RoutesVO> getRoutesTree(List<SysMenuVO> menu) {
        List<RoutesVO> routers = new LinkedList<>();
        for (SysMenuVO menuVO : menu) {
            RoutesVO routesVO = new RoutesVO();
            // 路由地址
            String path = this.getPath(menuVO);
            routesVO.setPath(path);
            // 组件路径
            String component = this.getComponent(menuVO);
            routesVO.setComponent(component);
            // 是否隐藏路由，当设置 true 的时候该路由不会再侧边栏出现
            routesVO.setHidden(BaseConstant.NUMBER_ONE == menuVO.getIsShow());
            // 路由名称
            routesVO.setName(StringUtils.capitalize(menuVO.getPath()));
            // 重定向地址
            String redirect = this.getRedirect(menuVO);
            routesVO.setRedirect(redirect);
            // 路由元信息
            MetaVO metaVO = new MetaVO();
            metaVO.setIcon(menuVO.getIcon());
            metaVO.setTitle(menuVO.getMenuName());
            routesVO.setMeta(metaVO);
            // 子路由
            List<SysMenuVO> children = menuVO.getChildren();
            if (CollUtil.isNotEmpty(children)) {
                routesVO.setChildren(getRoutesTree(children));
            }
            routers.add(routesVO);
        }
        return routers;
    }


    /**
     * 获取用户权限
     *
     * @param userId 用户id
     * @return
     */
    @Override
    public Set<String> selectPreGetByUserId(String userId) {
        Set<String> preSet = new HashSet<>();
        // 是否是超级管理员判断
        if (SecurityUtils.isAdmin(userId)) {
            preSet.add("*:*:*");
        } else {
            List<String> preList = sysMenuMapper.selectPreGetByUserId(userId);
            preList.forEach(item -> {
                if (StrUtil.isNotEmpty(item)) {
                    preSet.add(item);
                }
            });
        }
        return preSet;
    }


    /**
     * 根据用户查询菜单下拉框列表
     *
     * @param sysMenuDTO 菜单信息
     * @return 菜单数据
     */
    @Override
    public List<MenuTreeVO> selectMenuTreeList(SysMenuDTO sysMenuDTO) {
        List<SysMenuVO> sysMenuList = null;
        if (SecurityUtils.isAdmin(SecurityUtils.getAdmin().getId())) {
            sysMenuList = sysMenuMapper.selectMenuTreeList(sysMenuDTO);
        } else {
            sysMenuDTO.setUserId(SecurityUtils.getAdmin().getId());
            sysMenuList = sysMenuMapper.menuTreeByUserIdList(sysMenuDTO);
        }
        // 获取子菜单
        List<SysMenuVO> childrenList = getChildrenList(sysMenuList);
        return childrenList.stream().map(MenuTreeVO::new).collect(Collectors.toList());
    }


    /**
     * 根据角色id查询关联菜单
     *
     * @param roleId 角色id
     * @return 菜单id数据
     */
    @Override
    public List<String> getMenuListByRoleId(String roleId) {
        List<String> menuListByRoleId = sysMenuMapper.getMenuListByRoleId(roleId);
        return menuListByRoleId;
    }


    /**
     * 获取子菜单数据
     *
     * @param sysMenuVOList 菜单数据
     * @return
     */
    private List<SysMenuVO> getChildrenList(List<SysMenuVO> sysMenuVOList) {
        List<SysMenuVO> menuTreeList = sysMenuVOList;
        return getMenuList(menuTreeList);
    }


    /**
     * path路由地址
     *
     * @param menuVO
     * @return
     */
    private String getPath(SysMenuVO menuVO) {
        String path = menuVO.getPath();
        if ("0".equals(menuVO.getParentId()) && menuVO.getMenuType().equals(BaseConstant.TYPE_DIR)) {
            path = "/" + path;
        }
        return path;
    }

    /**
     * component路由组件路径
     *
     * @param menuVO
     * @return
     */
    private String getComponent(SysMenuVO menuVO) {
        String component = menuVO.getComponent();
        if ("0".equals(menuVO.getParentId())) {
            component = BaseConstant.LAYOUT;
        }
        return component;
    }

    /**
     * redirect重定向地址
     *
     * @param menuVO
     * @return
     */
    private String getRedirect(SysMenuVO menuVO) {
        String redirect = "";
        // TODO 更改:当此路由没有子路由的时候
        if ("0".equals(menuVO.getParentId())) {
            redirect = "/" + menuVO.getPath() + "/" + menuVO.getChildren().get(0).getPath();
        }
        return redirect;
    }


    /**
     * 组装菜单
     *
     * @param menuVOList 菜单数据
     * @return 菜单集合
     */
    private List<SysMenuVO> getMenuList(List<SysMenuVO> menuVOList) {
        List<SysMenuVO> menuVOS = new ArrayList<>();
        //获取所有父节点
        for (SysMenuVO sysMenuVO : menuVOList) {
            if (sysMenuVO.getParentId().equals("0")) {
                getChildList(sysMenuVO, menuVOList);
                menuVOS.add(sysMenuVO);
            }
        }
        return menuVOS;
    }


    /**
     * 获取子节点
     *
     * @param sysMenuVO  父节点
     * @param menuVOList 菜单数据
     */
    private void getChildList(SysMenuVO sysMenuVO, List<SysMenuVO> menuVOList) {
        List<SysMenuVO> childsList = new ArrayList<>();
        for (SysMenuVO menuVO : menuVOList) {
            if (menuVO.getParentId().equals(sysMenuVO.getId())) {
                childsList.add(menuVO);
            }
        }
        if (CollUtil.isEmpty(childsList)) {
            return;
        }
        sysMenuVO.setChildren(childsList);
        for (SysMenuVO childs :
                childsList) {
            getChildList(childs, menuVOList);
        }
    }
}
